package com.ruoyi.file.service.storage;

import com.ruoyi.file.domain.SysStorageConfig;
import com.ruoyi.file.domain.vo.UploadTokenVO;

import java.io.InputStream;
import java.time.Duration;

/**
 * 存储服务接口
 *
 * @author ruoyi
 */
public interface StorageService {

    /**
     * 上传文件
     *
     * @param inputStream 文件流
     * @param fileName    文件名
     * @param contentType 文件类型
     * @param config      存储配置
     * @return 文件路径
     */
    String uploadFile(InputStream inputStream, String fileName, String contentType, SysStorageConfig config);

    /**
     * 上传文件到指定路径
     *
     * @param inputStream 文件流
     * @param fileName    文件名
     * @param contentType 文件类型
     * @param config      存储配置
     * @param targetPath  目标路径
     * @return 文件路径
     */
    String uploadFile(InputStream inputStream, String fileName, String contentType, SysStorageConfig config, String targetPath);

    /**
     * 下载文件
     *
     * @param filePath 文件路径
     * @param config   存储配置
     * @return 文件流
     */
    InputStream downloadFile(String filePath, SysStorageConfig config);

    /**
     * 删除文件
     *
     * @param filePath 文件路径
     * @param config   存储配置
     * @return 是否成功
     */
    boolean deleteFile(String filePath, SysStorageConfig config);

    /**
     * 获取文件访问URL
     *
     * @param filePath 文件路径
     * @param config   存储配置
     * @return 文件URL
     */
    String getFileUrl(String filePath, SysStorageConfig config);

    /**
     * 获取预签名上传URL
     *
     * @param filePath   文件路径
     * @param config     存储配置
     * @param expiration 过期时间
     * @return 预签名上传URL
     */
    String getPresignedUploadUrl(String filePath, SysStorageConfig config, Duration expiration);

    /**
     * 获取预签名下载URL
     *
     * @param filePath   文件路径
     * @param config     存储配置
     * @param expiration 过期时间
     * @return 预签名下载URL
     */
    String getPresignedDownloadUrl(String filePath, SysStorageConfig config, Duration expiration);

    /**
     * 检查文件是否存在
     *
     * @param filePath 文件路径
     * @param config   存储配置
     * @return 是否存在
     */
    boolean fileExists(String filePath, SysStorageConfig config);

    /**
     * 创建存储桶
     *
     * @param bucketName 桶名称
     * @param config     存储配置
     * @return 是否成功
     */
    boolean createBucket(String bucketName, SysStorageConfig config);

    /**
     * 删除存储桶
     *
     * @param bucketName 桶名称
     * @param config     存储配置
     * @return 是否成功
     */
    boolean deleteBucket(String bucketName, SysStorageConfig config);

    /**
     * 检查存储桶是否存在
     *
     * @param bucketName 桶名称
     * @param config     存储配置
     * @return 是否存在
     */
    boolean bucketExists(String bucketName, SysStorageConfig config);

    /**
     * 获取存储桶列表
     *
     * @param config 存储配置
     * @return 桶名称列表
     */
    java.util.List<String> listBuckets(SysStorageConfig config);

    /**
     * 设置存储桶权限
     *
     * @param bucketName 桶名称
     * @param permission 权限类型：private(私有)、public-read(公共读)、public-read-write(公共读写)
     * @param config     存储配置
     * @return 是否成功
     */
    boolean setBucketPermission(String bucketName, String permission, SysStorageConfig config);

    /**
     * 获取存储桶权限
     *
     * @param bucketName 桶名称
     * @param config     存储配置
     * @return 权限类型
     */
    String getBucketPermission(String bucketName, SysStorageConfig config);

    /**
     * 生成直传令牌
     *
     * @param fileName 文件名
     * @param config   存储配置
     * @return 上传令牌
     */
    UploadTokenVO generateUploadToken(String fileName, SysStorageConfig config);

    /**
     * 生成直传令牌（支持自定义目录路径）
     *
     * @param fileName 文件名
     * @param config   存储配置
     * @param dirPath  目录路径（可选）
     * @return 上传令牌
     */
    default UploadTokenVO generateUploadToken(String fileName, SysStorageConfig config, String dirPath) {
        // 默认实现：忽略dirPath，使用原有逻辑
        return generateUploadToken(fileName, config);
    }

    // ==================== S3原生分片上传接口 ====================

    /**
     * 初始化分片上传
     *
     * @param fileName 文件名
     * @param config   存储配置
     * @return 上传ID
     */
    String initMultipartUpload(String fileName, SysStorageConfig config);

    /**
     * 获取分片预签名上传URL
     *
     * @param fileName   文件名
     * @param uploadId   上传ID
     * @param partNumber 分片号
     * @param config     存储配置
     * @return 预签名URL
     */
    String getPresignedUploadUrl(String fileName, String uploadId, int partNumber, SysStorageConfig config);

    /**
     * 完成分片上传
     *
     * @param fileName 文件名
     * @param uploadId 上传ID
     * @param parts    分片信息列表
     * @param config   存储配置
     * @return 是否成功
     */
    boolean completeMultipartUpload(String fileName, String uploadId, java.util.List<com.ruoyi.file.domain.dto.CompleteMultipartRequest.PartInfo> parts, SysStorageConfig config);

    /**
     * 取消分片上传
     *
     * @param fileName 文件名
     * @param uploadId 上传ID
     * @param config   存储配置
     * @return 是否成功
     */
    boolean abortMultipartUpload(String fileName, String uploadId, SysStorageConfig config);

    /**
     * 批量获取分片预签名上传URL
     *
     * @param fileName   文件名
     * @param uploadId   上传ID
     * @param totalParts 总分片数量
     * @param config     存储配置
     * @return 预签名URL列表
     */
    default java.util.List<String> getBatchPresignedUploadUrls(String fileName, String uploadId, int totalParts, SysStorageConfig config) {
        java.util.List<String> urls = new java.util.ArrayList<>();
        for (int i = 1; i <= totalParts; i++) {
            String url = getPresignedUploadUrl(fileName, uploadId, i, config);
            urls.add(url);
        }
        return urls;
    }

    /**
     * 直接上传分片（用于后端转发模式）
     *
     * @param fileName   文件名
     * @param uploadId   上传ID
     * @param partNumber 分片号
     * @param inputStream 分片数据流
     * @param config     存储配置
     * @return 分片的ETag
     */
    String uploadPart(String fileName, String uploadId, int partNumber, java.io.InputStream inputStream, SysStorageConfig config);

    // ==================== CORS配置接口 ====================

    /**
     * 配置存储桶的CORS规则
     *
     * @param bucketName 桶名称
     * @param config     存储配置
     * @return 是否成功
     */
    default boolean configureBucketCors(String bucketName, SysStorageConfig config) {
        // 默认实现，子类可以重写
        return false;
    }

    /**
     * 获取存储桶的CORS配置
     *
     * @param bucketName 桶名称
     * @param config     存储配置
     * @return CORS配置信息
     */
    default String getBucketCors(String bucketName, SysStorageConfig config) {
        // 默认实现，子类可以重写
        return null;
    }

    /**
     * 删除存储桶的CORS配置
     *
     * @param bucketName 桶名称
     * @param config     存储配置
     * @return 是否成功
     */
    default boolean deleteBucketCors(String bucketName, SysStorageConfig config) {
        // 默认实现，子类可以重写
        return false;
    }
}
